<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>react实用库（转载） | 破破的QQ空间</title><meta name="author" content="破破"><meta name="copyright" content="破破"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="基础 React Infinite ScrollerReact Infinite Scroller 用于在 React 项目中无限滚动加载内容。npm 地址：https:&#x2F;&#x2F;www.npmjs.com&#x2F;package&#x2F;react-infinite-scroller  react-dndReact DnD 是 React 和 Redux 核心作者 Dan Abramov 创造的一组 React 高阶">
<meta property="og:type" content="article">
<meta property="og:title" content="react实用库（转载）">
<meta property="og:url" content="https://leiboy.gitee.io/blog/2022/04/07/react%E5%AE%9E%E7%94%A8%E5%BA%93%EF%BC%88%E8%BD%AC%E8%BD%BD%EF%BC%89/index.html">
<meta property="og:site_name" content="破破的QQ空间">
<meta property="og:description" content="基础 React Infinite ScrollerReact Infinite Scroller 用于在 React 项目中无限滚动加载内容。npm 地址：https:&#x2F;&#x2F;www.npmjs.com&#x2F;package&#x2F;react-infinite-scroller  react-dndReact DnD 是 React 和 Redux 核心作者 Dan Abramov 创造的一组 React 高阶">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://leiboy.gitee.io/blog/2022/04/07/react%E5%AE%9E%E7%94%A8%E5%BA%93%EF%BC%88%E8%BD%AC%E8%BD%BD%EF%BC%89/react-logo.png">
<meta property="article:published_time" content="2022-04-07T08:48:51.000Z">
<meta property="article:modified_time" content="2024-07-01T14:13:29.127Z">
<meta property="article:author" content="破破">
<meta property="article:tag" content="react">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://leiboy.gitee.io/blog/2022/04/07/react%E5%AE%9E%E7%94%A8%E5%BA%93%EF%BC%88%E8%BD%AC%E8%BD%BD%EF%BC%89/react-logo.png"><link rel="shortcut icon" href="/blog/img/favicon.png"><link rel="canonical" href="https://leiboy.gitee.io/blog/2022/04/07/react%E5%AE%9E%E7%94%A8%E5%BA%93%EF%BC%88%E8%BD%AC%E8%BD%BD%EF%BC%89/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/blog/css/index.css?v=4.14.0-b3"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.1/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.35/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>(()=>{
      const saveToLocal = {
        set: (key, value, ttl) => {
          if (ttl === 0) return
          const now = Date.now()
          const expiry = now + ttl * 86400000
          const item = {
            value,
            expiry
          }
          localStorage.setItem(key, JSON.stringify(item))
        },
      
        get: key => {
          const itemStr = localStorage.getItem(key)
      
          if (!itemStr) {
            return undefined
          }
          const item = JSON.parse(itemStr)
          const now = Date.now()
      
          if (now > item.expiry) {
            localStorage.removeItem(key)
            return undefined
          }
          return item.value
        }
      }
      
      window.btf = {
        saveToLocal: saveToLocal,
        getScript: (url, attr = {}) => new Promise((resolve, reject) => {
          const script = document.createElement('script')
          script.src = url
          script.async = true
          script.onerror = reject
          script.onload = script.onreadystatechange = function() {
            const loadState = this.readyState
            if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
            script.onload = script.onreadystatechange = null
            resolve()
          }

          Object.keys(attr).forEach(key => {
            script.setAttribute(key, attr[key])
          })

          document.head.appendChild(script)
        }),

        getCSS: (url, id = false) => new Promise((resolve, reject) => {
          const link = document.createElement('link')
          link.rel = 'stylesheet'
          link.href = url
          if (id) link.id = id
          link.onerror = reject
          link.onload = link.onreadystatechange = function() {
            const loadState = this.readyState
            if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
            link.onload = link.onreadystatechange = null
            resolve()
          }
          document.head.appendChild(link)
        }),

        addGlobalFn: (key, fn, name = false, parent = window) => {
          const pjaxEnable = false
          if (!pjaxEnable && key.startsWith('pjax')) return

          const globalFn = parent.globalFn || {}
          const keyObj = globalFn[key] || {}
    
          if (name && keyObj[name]) return
    
          name = name || Object.keys(keyObj).length
          keyObj[name] = fn
          globalFn[key] = keyObj
          parent.globalFn = globalFn
        }
      }
    
      const activateDarkMode = () => {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      const activateLightMode = () => {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }

      btf.activateDarkMode = activateDarkMode
      btf.activateLightMode = activateLightMode
      
      const t = saveToLocal.get('theme')
    
        if (t === 'dark') activateDarkMode()
        else if (t === 'light') activateLightMode()
      
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
      const detectApple = () => {
        if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
          document.documentElement.classList.add('apple')
        }
      }
      detectApple()
    })()</script><script>const GLOBAL_CONFIG = {
  root: '/blog/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false,"highlightFullpage":true,"highlightMacStyle":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  dateSuffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  infinitegrid: {
    js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.11.1/dist/infinitegrid.min.js',
    buttonText: '加载更多'
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isAnchor: false,
  percent: {
    toc: true,
    rightside: false,
  },
  autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'react实用库（转载）',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2024-07-01 22:13:29'
}</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">10</div></a><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">7</div></a><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">2</div></a></div><hr class="custom-hr"/></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('/blog/2022/04/07/react%E5%AE%9E%E7%94%A8%E5%BA%93%EF%BC%88%E8%BD%AC%E8%BD%BD%EF%BC%89/react-logo.png')"><nav id="nav"><span id="blog-info"><a href="/blog/" title="破破的QQ空间"><span class="site-name">破破的QQ空间</span></a></span><div id="menus"><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav><div id="post-info"><h1 class="post-title">react实用库（转载）</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2022-04-07T08:48:51.000Z" title="发表于 2022-04-07 16:48:51">2022-04-07</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-07-01T14:13:29.127Z" title="更新于 2024-07-01 22:13:29">2024-07-01</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/blog/categories/react/">react</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="react实用库（转载）"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h2 id="基础"><a href="#基础" class="headerlink" title="基础"></a>基础</h2><ol>
<li><p>React Infinite Scroller<br>React Infinite Scroller 用于在 React 项目中无限滚动加载内容。<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/react-infinite-scroller">https://www.npmjs.com/package/react-infinite-scroller</a></p>
</li>
<li><p>react-dnd<br>React DnD 是 React 和 Redux 核心作者 Dan Abramov 创造的一组 React 高阶组件，可以在保持组件分离的前提下帮助构建复杂的拖放接口。主要用于组件的拖放。<br><a target="_blank" rel="noopener" href="https://www.npmjs.com/package/react-dnd">https://www.npmjs.com/package/react-dnd</a></p>
</li>
<li><p>react-beautiful-dnd<br>react-beautiful-dnd 是一款美观且简单易用的 React 列表拖拽库。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-beautiful-dnd">www.npmjs.com/package/react-beautiful-dnd</a></p>
</li>
<li><p>react-icons<br>使用 react-icons 可以轻松地在 React 项目中包含流行的图标。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-icons">www.npmjs.com/package/react-icons</a></p>
</li>
<li><p>react-share<br>react-share 是一个 React 的社交媒体分享按钮和分享次数库。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-share">www.npmjs.com/package/react-share</a></p>
</li>
<li><p>create-react-app<br>Create React App 是一个命令行界面工具，让您无需任何配置即可快速创建和运行 React 应用程序。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/create-react-app">www.npmjs.com/package/create-react-app</a></p>
</li>
<li><p>react-intl<br>React Intl 提供了一个 React 组件和用于国际化 React Web 应用的 Mixin。它提供一个格式化日期、数字、字符串消息的描述方式。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-intl">www.npmjs.com/package/react-intl</a></p>
</li>
<li><p>react-router<br>react-router 是个用于 React.js 的路由解决方案（routing solution）。它轻松可以同步你的 app 和 URL，同时给嵌套，转换，和服务端渲染一流的支持。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-router">www.npmjs.com/package/react-router</a></p>
</li>
<li><p>React Virtualized<br>react-virtualized 是一个以高效渲染大型列表和表格数据的响应式组件，可以用来解决长列表渲染问题。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-virtualized">www.npmjs.com/package/react-virtualized</a></p>
</li>
</ol>
<h2 id="状态管理"><a href="#状态管理" class="headerlink" title="状态管理"></a>状态管理</h2><ol start="10">
<li><p>redux<br>Redux 是 JavaScript 状态容器，提供可预测化的状态管理。可以让你构建一致化的应用，运行于不同的环境（客户端、服务器、原生应用），并且易于测试。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/redux">www.npmjs.com/package/redux</a></p>
</li>
<li><p>react-redux<br>Redux 官方提供的 React 绑定库。 具有高效且灵活的特性。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-redux">www.npmjs.com/package/react-redux</a></p>
</li>
<li><p>MobX<br>MobX 是一个经久考验的库,使得状态管理简单而且透明、可伸缩的应用功能反应性编程(TFRP)。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/mobx">https://www.npmjs.com/package/mobx</a></p>
</li>
<li><p>redux-saga<br>redux-saga 是一个用于管理应用程序 Side Effect（副作用，例如异步获取数据，访问浏览器缓存等）的库，它的目标是让副作用管理更容易，执行更高效，测试更简单，在处理故障时更容易。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/redux-saga">www.npmjs.com/package/redux-saga</a></p>
</li>
<li><p>redux-thunk<br>Redux 的 Thunk 中间件。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/redux-thunk">www.npmjs.com/package/redux-thunk</a></p>
<h2 id="组件"><a href="#组件" class="headerlink" title="组件"></a>组件</h2></li>
<li><p>Ant Design<br>antd 是基于 Ant Design 设计体系的 React UI 组件库，主要用于研发企业级中后台产品。<br>​<br>官网地址：<a target="_blank" rel="noopener" href="https://ant.design/index-cn">https://ant.design/index-cn</a></p>
</li>
<li><p>React Select<br>React Select 是一个开箱即用的 Select 控件。<br>官网地址：react-select.com&#x2F;home</p>
</li>
<li><p>React Hot Toast<br>React Hot Toast 是一个热门的通知库，包含很多通知的样式。<br>官网地址：react-hot-toast.com&#x2F;</p>
</li>
<li><p>React Content Loader<br>React Content Loader 可以用于生成列表加载占位组件。<br>官网地址：skeletonreact.com&#x2F;</p>
</li>
<li><p>Sweet Alert<br>Sweet Alert 是一个弹窗组件，包含很多弹窗样式。<br>官网地址：sweetalert.js.org&#x2F;</p>
</li>
<li><p>draftjs<br>Draft JS 是一个富文本编辑器库。可以无缝地融入 React 应用程序。<br>官网地址：draftjs.org&#x2F;</p>
</li>
<li><p>react-slick<br>React Slick 是一个 React 轮播组件。<br>官网地址：react-slick.neostack.com&#x2F;</p>
</li>
<li><p>Material-UI<br>Material-UI 是一个简单的、可定制的组件库，用于构建更快、更漂亮、更易使用的 React 应用程序。<br>官网地址：<a target="_blank" rel="noopener" href="https://mui.com/zh/getting-started/usage/">https://mui.com/zh/getting-started/usage/</a></p>
</li>
<li><p>react-bootstrap<br>React Bootstrap 是一个由 React 构建的 Bootstrap 4 组件。<br>官网地址：react-bootstrap.github.io&#x2F;</p>
</li>
<li><p>react-custom-scrollbars<br>react-custom-scrollbars 是一个滚动条组件库，可以在 web 和移动端流畅的使用滚动条，并且可以完全自己定制<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/react-custom-scrollbars">https://www.npmjs.com/package/react-custom-scrollbars</a></p>
</li>
<li><p>react-dropdown<br>react-dropdown 是一个简单的下拉组件，灵感来自于 react-select。<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/react-dropdown">https://www.npmjs.com/package/react-dropdown</a></p>
</li>
<li><p>react-horizontal-scrolling-menu<br>react-horizontal-scrolling-menu 是一个水平滚动菜单组件。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/react-horizontal-scrolling-menu">https://www.npmjs.com/package/react-horizontal-scrolling-menu</a></p>
</li>
<li><p>react-calendar<br>react-calendar 是一个 React 的日历组件。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/react-calendar">https://www.npmjs.com/package/react-calendar</a></p>
</li>
<li><p>react-datepicker<br>react-datepicker 是一个日期选择组件。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/react-datepicker">https://www.npmjs.com/package/react-datepicker</a></p>
</li>
<li><p>react-table<br>react-table 是一个强大的表格组件。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/react-table">https://www.npmjs.com/package/react-table</a></p>
</li>
<li><p>react-awesome-button<br>react-awesome-button 是一个按钮组件库。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/react-awesome-button">https://www.npmjs.com/package/react-awesome-button</a></p>
</li>
<li><p>react-compound-slider<br>react-compound-slider 是一个滑块组件。<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/react-compound-slider">https://www.npmjs.com/package/react-compound-slider</a></p>
</li>
<li><p>react-checkbox-tree<br>react-checkbox-tree 是一个复选框组件。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-checkbox-tree">www.npmjs.com/package/react-checkbox-tree</a></p>
</li>
<li><p>recharts<br>recharts 是一个 React 图表库。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/recharts">www.npmjs.com/package/recharts</a></p>
</li>
<li><p>react-modal<br>react-modal 是一个静态动画库组件库。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-modal">www.npmjs.com/package/react-modal</a></p>
</li>
<li><p>react-responsive-carousel<br>react-responsive-carousel 是一个响应式的轮播组件库。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-responsive-carousel">www.npmjs.com/package/react-responsive-carousel</a></p>
</li>
<li><p>react-image-lightbox<br>react-image-lightbox 是一个用于显示图片的组件库。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-image-lightbox">www.npmjs.com/package/react-image-lightbox</a></p>
</li>
<li><p>react-tabs<br>react-tabs 是一个选项卡组件。<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-tabs">www.npmjs.com/package/react-tabs</a></p>
</li>
<li><p>rebass<br>Rebass 是一个用于构建响应式 WEB 应用的 React UI 工具包，它有 60 多种可定制的基础组件，而且风格样式分离，不需要编写自定义的 CSS。<br>​<br>官网地址：rebassjs.org&#x2F;</p>
</li>
<li><p>react-suite<br>React Suite 是一套转为后端打造的企业级 UI 组件库，它由 HYPERS 前端团队与 UX 团队共同打造，有大量的通用组件和功能，而且支持 Typescript 与 Flow, 支持服务端渲染。<br>​<br>官网地址：rsuitejs.com&#x2F;</p>
<h2 id="动画"><a href="#动画" class="headerlink" title="动画"></a>动画</h2></li>
<li><p>react-spring<br>react-spring 是基于 spring-physics（弹簧物理）的 react 动画库，动画效果更加流畅、自然。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-spring">www.npmjs.com/package/react-spring</a></p>
</li>
<li><p>react-motion<br>react-motion 是一个强大的 react 动画库。<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-motion">www.npmjs.com/package/react-motion</a></p>
</li>
<li><p>react-transition-group<br>react-transition-group 是一个专为动画设计的库。<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-transition-group">www.npmjs.com/package/react-transition-group</a></p>
</li>
<li><p>react-spinner<br>react-spinner 用来创建加载组件。<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-spinner">www.npmjs.com/package/react-spinner</a></p>
<h2 id="HTTP"><a href="#HTTP" class="headerlink" title="HTTP"></a>HTTP</h2></li>
<li><p>Axios<br>Axios 是一个基于 promise 的 HTTP 库，可以用在浏览器和 node.js 中。<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/axios">www.npmjs.com/package/axios</a></p>
</li>
<li><p>apisauce<br>apisauce 是一个建立在 axios 之上的 http 客户端。官方介绍：Axios + standardized errors + request&#x2F;response transforms.<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/apisauce">www.npmjs.com/package/apisauce</a></p>
</li>
<li><p>SuperAgent<br>SuperAgent 是一个轻量的 Ajax API，服务器端（Node.js）客户端（浏览器端）均可使用，SuperAgent 具有学习曲线低、使用简单、可读性好的特点,可作为客户端请求代理模块使用，当想处理 get,post,put,delete,head 请求时，可以考虑使用 SuperAgent。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/superagent">https://www.npmjs.com/package/superagent</a></p>
<h2 id="CSS"><a href="#CSS" class="headerlink" title="CSS"></a>CSS</h2></li>
<li><p>styled-components<br>styled-components 可以在 JavaScript 代码中使用 CSS 来设置 React 组件的样式。通过这个库可以自定义组件的样式，它会将给定的样式包装成一个组件，可以直接使用这个组件，也不需要组件和样式之间的映射，即创建后就是一个正常的 React 组件。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/styled-components">www.npmjs.com/package/styled-components</a></p>
</li>
<li><p>emotion<br>emotion 是 JS 库中一种高效灵活的 CSS。基于 JS 库中的许多其他 CSS，它允许您使用字符串或对象样式快速设置应用程序样式。它具有可预测的组成，以避免 CSS 的特殊性问题。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/emotion">www.npmjs.com/package/emotion</a></p>
<h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2></li>
<li><p>@testing-library&#x2F;react<br>React Testing Library 基于 DOM Testing Library 的基础上添加一些 API，主要用于测试 React 组件。该库在使用过程并不关注组件的内部实现，而是更关注测试。该库基于 react-dom 和 react-dom&#x2F;test-utils，是以上两者的轻量实现。<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/@testing-library/react">https://www.npmjs.com/package/@testing-library/react</a></p>
</li>
<li><p>Enzyme<br>Enzyme 来自 airbnb 公司，是一个用于 React 的 JavaScript 测试工具，方便你判断、操纵和遍历 React Components 输出。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/enzyme">https://www.npmjs.com/package/enzyme</a></p>
<p>八、表单</p>
</li>
<li><p>react-hook-form<br>React Hook Form 是一个高性能、灵活、易拓展、易于使用的表单校验库，用于 React Web＆Native 的表单验证。<br>​<br>官网地址：react-hook-form.com&#x2F;</p>
</li>
<li><p>Formik<br>Formik 是由 React 组件和 hooks 组成，它内置了表单的 state 管理操作，无需我们在单独为表单建立 state，同时使用了 Context，能够让表单组件多层嵌套，不再需要我们一层层传递。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/formik">https://www.npmjs.com/package/formik</a></p>
</li>
<li><p>react-use-form-state<br>react-use-form-state 是一个小型 React Hook，它使用原生表单输入元素来简化管理表单的状态。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-use-form-state">www.npmjs.com/package/react-use-form-state</a></p>
</li>
</ol>
<h2 id="自定义-Hooks"><a href="#自定义-Hooks" class="headerlink" title="自定义 Hooks"></a>自定义 Hooks</h2><ol start="54">
<li>use-clippy<br>use-clippy 是一个用 TypeScript 实现的自定义 React Hook，可以用于读取和写入用户的剪贴板。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/use-clippy">www.npmjs.com/package/use-clippy</a></li>
<li>react-window-communication-hook<br>react-window-communication-hook 可以实现在浏览器上下文（窗口、选项卡、iframes）之间进行通信。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-window-communication-hook">www.npmjs.com/package/react-window-communication-hook</a></li>
<li>react-speech-kit<br>react-speech-kit 是一个用于浏览器内语音识别和语音合成的 React hook。简单来说就是可以将声音识别为文字，将文字合成为语音。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-speech-kit">www.npmjs.com/package/react-speech-kit</a></li>
<li>react-script-hook<br>react-script-hook 是一个用于动态加载（并在加载时通知）外部脚本的钩子。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-script-hook">www.npmjs.com/package/react-script-hook</a></li>
<li>use-mouse-action<br>use-mouse-action 是一个有三个 React hook 的库，用于侦听元素或 JSX 元素上的鼠标事件。 包括鼠标操作、鼠标按下、鼠标抬起事件。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/use-mouse-action">www.npmjs.com/package/use-mouse-action</a></li>
<li>@rehooks&#x2F;online-status<br>@rehooks&#x2F;online-status 用于检查网络状态以确定用户是否已连接到网络。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/@rehooks/online-status">www.npmjs.com/package/@rehooks/online-status</a></li>
<li>@rehooks&#x2F;document-title<br>@rehooks&#x2F;document-title 用于更新页面标题（显示在浏览器的选项卡中）。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/@rehooks/document-title">www.npmjs.com/package/@rehooks/document-title</a></li>
<li>useHooks<br>自定义 hook 库，包含很多实用的 Hooks。<br>​<br>官网地址：usehooks.com&#x2F;</li>
<li>react-hanger<br>react-hanger 是一个自定义 React Hooks 库，它包含很多实用的自定义 hooks。<br>​<br>npm 地址：<a target="_blank" rel="noopener" href="http://www.npmjs.com/package/react-hanger">www.npmjs.com/package/react-hanger</a></li>
</ol>
<p>转载至 <a target="_blank" rel="noopener" href="https://juejin.cn/post/7036162494573838367">https://juejin.cn/post/7036162494573838367</a></p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta"><i class="fas fa-circle-user fa-fw"></i>文章作者: </span><span class="post-copyright-info"><a href="https://leiboy.gitee.io/blog">破破</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta"><i class="fas fa-square-arrow-up-right fa-fw"></i>文章链接: </span><span class="post-copyright-info"><a href="https://leiboy.gitee.io/blog/2022/04/07/react%E5%AE%9E%E7%94%A8%E5%BA%93%EF%BC%88%E8%BD%AC%E8%BD%BD%EF%BC%89/">https://leiboy.gitee.io/blog/2022/04/07/react%E5%AE%9E%E7%94%A8%E5%BA%93%EF%BC%88%E8%BD%AC%E8%BD%BD%EF%BC%89/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta"><i class="fas fa-circle-exclamation fa-fw"></i>版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://leiboy.gitee.io/blog" target="_blank">破破的QQ空间</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/blog/tags/react/">react</a></div><div class="post_share"><div class="social-share" data-image="/blog/2022/04/07/react%E5%AE%9E%E7%94%A8%E5%BA%93%EF%BC%88%E8%BD%AC%E8%BD%BD%EF%BC%89/react-logo.png" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/blog/2022/07/01/js%E4%BB%A3%E7%A0%81%E9%A2%98/" title="js代码题"><img class="cover" src="/blog/2022/07/01/js%E4%BB%A3%E7%A0%81%E9%A2%98/js%E5%9B%BE%E7%89%87.jpg" onerror="onerror=null;src='/blog/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">js代码题</div></div></a></div><div class="next-post pull-right"><a href="/blog/2022/04/02/React%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E8%A1%A8%E5%8D%95%E5%AE%9E%E7%8E%B0/" title="React中的动态表单实现"><img class="cover" src="/blog/2022/04/02/React%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E8%A1%A8%E5%8D%95%E5%AE%9E%E7%8E%B0/react-logo.png" onerror="onerror=null;src='/blog/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">React中的动态表单实现</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><div><a href="/blog/2022/04/02/React%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E8%A1%A8%E5%8D%95%E5%AE%9E%E7%8E%B0/" title="React中的动态表单实现"><img class="cover" src="/blog/2022/04/02/React%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E8%A1%A8%E5%8D%95%E5%AE%9E%E7%8E%B0/react-logo.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-04-02</div><div class="title">React中的动态表单实现</div></div></a></div><div><a href="/blog/2023/03/18/React%E6%A8%A1%E6%8B%9F%E7%A7%BB%E5%85%A5title%E6%8F%90%E7%A4%BA/" title="React模拟移入title提示"><img class="cover" src="/blog/2023/03/18/React%E6%A8%A1%E6%8B%9F%E7%A7%BB%E5%85%A5title%E6%8F%90%E7%A4%BA/react-logo.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2023-03-18</div><div class="title">React模拟移入title提示</div></div></a></div><div><a href="/blog/2022/08/02/useContext%E6%A8%A1%E6%8B%9Fredux/" title="useContext模拟redux"><img class="cover" src="/blog/2022/08/02/useContext%E6%A8%A1%E6%8B%9Fredux/react-logo.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-08-02</div><div class="title">useContext模拟redux</div></div></a></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/blog/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">破破</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">10</div></a><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">7</div></a><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">2</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9F%BA%E7%A1%80"><span class="toc-number">1.</span> <span class="toc-text">基础</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86"><span class="toc-number">2.</span> <span class="toc-text">状态管理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6"><span class="toc-number">3.</span> <span class="toc-text">组件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8A%A8%E7%94%BB"><span class="toc-number">4.</span> <span class="toc-text">动画</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP"><span class="toc-number">5.</span> <span class="toc-text">HTTP</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#CSS"><span class="toc-number">6.</span> <span class="toc-text">CSS</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B5%8B%E8%AF%95"><span class="toc-number">7.</span> <span class="toc-text">测试</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89-Hooks"><span class="toc-number">8.</span> <span class="toc-text">自定义 Hooks</span></a></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/blog/2023/03/18/React%E6%A8%A1%E6%8B%9F%E7%A7%BB%E5%85%A5title%E6%8F%90%E7%A4%BA/" title="React模拟移入title提示"><img src="/blog/2023/03/18/React%E6%A8%A1%E6%8B%9F%E7%A7%BB%E5%85%A5title%E6%8F%90%E7%A4%BA/react-logo.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="React模拟移入title提示"/></a><div class="content"><a class="title" href="/blog/2023/03/18/React%E6%A8%A1%E6%8B%9F%E7%A7%BB%E5%85%A5title%E6%8F%90%E7%A4%BA/" title="React模拟移入title提示">React模拟移入title提示</a><time datetime="2023-03-18T14:58:49.000Z" title="发表于 2023-03-18 22:58:49">2023-03-18</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2023/03/08/React%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6%E6%9C%89%E5%93%AA%E4%BA%9B%E4%BC%98%E7%82%B9%E5%92%8C%E7%BC%BA%E7%82%B9/" title="React高阶组件有哪些优点和缺点"><img src="/blog/2023/03/08/React%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6%E6%9C%89%E5%93%AA%E4%BA%9B%E4%BC%98%E7%82%B9%E5%92%8C%E7%BC%BA%E7%82%B9/react-logo.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="React高阶组件有哪些优点和缺点"/></a><div class="content"><a class="title" href="/blog/2023/03/08/React%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6%E6%9C%89%E5%93%AA%E4%BA%9B%E4%BC%98%E7%82%B9%E5%92%8C%E7%BC%BA%E7%82%B9/" title="React高阶组件有哪些优点和缺点">React高阶组件有哪些优点和缺点</a><time datetime="2023-03-08T14:58:49.000Z" title="发表于 2023-03-08 22:58:49">2023-03-08</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/08/02/useContext%E6%A8%A1%E6%8B%9Fredux/" title="useContext模拟redux"><img src="/blog/2022/08/02/useContext%E6%A8%A1%E6%8B%9Fredux/react-logo.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="useContext模拟redux"/></a><div class="content"><a class="title" href="/blog/2022/08/02/useContext%E6%A8%A1%E6%8B%9Fredux/" title="useContext模拟redux">useContext模拟redux</a><time datetime="2022-08-02T14:58:49.000Z" title="发表于 2022-08-02 22:58:49">2022-08-02</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/07/13/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E9%9D%A2%E8%AF%95%E9%A2%98/" title="小程序面试题"><img src="/blog/2022/07/13/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E9%9D%A2%E8%AF%95%E9%A2%98/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%9B%BE%E6%A0%87.jpeg" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="小程序面试题"/></a><div class="content"><a class="title" href="/blog/2022/07/13/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E9%9D%A2%E8%AF%95%E9%A2%98/" title="小程序面试题">小程序面试题</a><time datetime="2022-07-13T15:39:09.000Z" title="发表于 2022-07-13 23:39:09">2022-07-13</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2022/07/10/HTML%E5%92%8CCSS%E9%9D%A2%E8%AF%95%E9%A2%98/" title="HTML和CSS面试题"><img src="/blog/2022/07/10/HTML%E5%92%8CCSS%E9%9D%A2%E8%AF%95%E9%A2%98/csslogo.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="HTML和CSS面试题"/></a><div class="content"><a class="title" href="/blog/2022/07/10/HTML%E5%92%8CCSS%E9%9D%A2%E8%AF%95%E9%A2%98/" title="HTML和CSS面试题">HTML和CSS面试题</a><time datetime="2022-07-10T14:22:28.000Z" title="发表于 2022-07-10 22:22:28">2022-07-10</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2024 By 破破</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/blog/js/utils.js?v=4.14.0-b3"></script><script src="/blog/js/main.js?v=4.14.0-b3"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.35/dist/fancybox/fancybox.umd.min.js"></script><div class="js-pjax"><script>(() => {
  const runMermaid = (ele) => {
    window.loadMermaid = true
    const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'default'

    Array.from(ele).forEach((item, index) => {
      const mermaidSrc = item.firstElementChild
      const mermaidThemeConfig = '%%{init:{ \'theme\':\'' + theme + '\'}}%%\n'
      const mermaidID = 'mermaid-' + index
      const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent

      const renderFn = mermaid.render(mermaidID, mermaidDefinition)

      const renderV10 = () => {
        renderFn.then(({svg}) => {
          mermaidSrc.insertAdjacentHTML('afterend', svg)
        })
      }

      const renderV9 = svg => {
        mermaidSrc.insertAdjacentHTML('afterend', svg)
      }

      typeof renderFn === 'string' ? renderV9(renderFn) : renderV10()
    })
  }

  const codeToMermaid = () => {
    const codeMermaidEle = document.querySelectorAll('pre > code.mermaid')
    if (codeMermaidEle.length === 0) return
    
    codeMermaidEle.forEach(ele => {
      const newEle = document.createElement('div')
      newEle.className = 'mermaid-wrap'
      newEle.innerHTML = `<pre class="mermaid-src" hidden>${ele.textContent}</pre>`
      ele.parentNode.replaceWith(newEle)
    })
  }

  const loadMermaid = () => {
    if (false) codeToMermaid()
    const $mermaid = document.querySelectorAll('#article-container .mermaid-wrap')
    if ($mermaid.length === 0) return

    const runMermaidFn = () => runMermaid($mermaid)
    btf.addGlobalFn('themeChange', runMermaidFn, 'mermaid')
    window.loadMermaid ? runMermaidFn() : btf.getScript('https://cdn.jsdelivr.net/npm/mermaid@10.9.0/dist/mermaid.min.js').then(runMermaidFn)
  }
  
  btf.addGlobalFn('encrypt', loadMermaid, 'mermaid')
  window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid)
})()</script></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>